﻿#include "mainwindow.h"
#include "customWrapperedFunc.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include "LogExecuterIncludes/LogExecuter.h"
#include "LogExecuterIncludes/WarpperedFunc.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->resize(1500,900);
    ui->actionExecute->setEnabled(false);
    ui->comboBox->addItem("ExecuteNextMode");
    ui->comboBox->addItem("ExecuteAllMode");
    //this->setWindowState(Qt::WindowMaximized);
    QFont font=ui->plainTextEdit->font();

    font.setPointSize(15);
    ui->plainTextEdit->setFont(font);
    ui->plainTextEdit_2->setFont(font);
    ui->lineEdit->setPlaceholderText("show original log file path here");
    ui->lineEdit_2->setPlaceholderText("show output log file path here");
    QFont fontList=ui->listWidget->font();

    fontList.setPointSize(15);
    ui->listWidget->setFont(fontList);
}

MainWindow::~MainWindow()
{
    delete ui;
    delete exec;
}

bool MainWindow::executerIsCreated()
{
    //warning:reset exec to nullptr after exec object is deconstructed
    return exec==nullptr?false:true;
}

void MainWindow::initTableWidget()
{
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);

    int maxParasSize=exec->getParser().getMaxParasSize();
    ui->tableWidget->setColumnCount(exec->getParser().getMaxParasSize()*4+3);
    ui->tableWidget->setRowCount(exec->getCalls().size());
    QStringList headerlist;
    QFont font = ui->tableWidget->horizontalHeader()->font();
    font.setBold(true);
    font.setPointSize(15);
    ui->tableWidget->horizontalHeader()->setFont(font);

    //ui->tableWidget->setFont(font);
    headerlist.push_back("functionName");
    headerlist.push_back("action");
    headerlist.push_back("time");
    for(int i=1;i<=maxParasSize;i++){
        headerlist.push_back("parameter"+QString::number(i)+".name");
        headerlist.push_back("parameter"+QString::number(i)+".type");
        headerlist.push_back("parameter"+QString::number(i)+".size");
        headerlist.push_back("parameter"+QString::number(i)+".value");
    }
    ui->tableWidget->setHorizontalHeaderLabels(headerlist);
    ui->tableWidget->horizontalHeader()->setResizeContentsPrecision(QHeaderView::Stretch);
    ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableWidget->setStyleSheet("selection-background-color:rgb(255,209,128)");
    font.setBold(false);
    ui->tableWidget->setFont(font);
    ui->tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter);
    if(exec->getCalls().size()!=0){
        std::vector<FunctionCall> calls=exec->getCalls();
        for(int i=0;i<calls.size();i++){
            QString name=QString::fromStdString(calls[i].name);
            QString action=QString::fromStdString(calls[i].action);
            QString time=QString::fromStdString(calls[i].time);
            QTableWidgetItem* item=new QTableWidgetItem(name);
            ui->tableWidget->setItem(i,0,item);
            item=new QTableWidgetItem(action);
            ui->tableWidget->setItem(i,1,item);
            item=new QTableWidgetItem(time);
            ui->tableWidget->setItem(i,2,item);
            std::vector<Parameter> paras=calls[i].parameters;
            for(int j=0;j<paras.size();j++){
                QString paraName=QString::fromStdString(paras[j].name);
                QString paraType=QString::fromStdString(paras[j].type);
                QString paraSize=QString::number(paras[j].size);
                QString paraStrVal=QString::fromStdString(paras[j].stringValue);
                item=new QTableWidgetItem(paraName);
                ui->tableWidget->setItem(i,4*j+3,item);
                item=new QTableWidgetItem(paraType);
                ui->tableWidget->setItem(i,4*j+4,item);
                item=new QTableWidgetItem(paraSize);
                ui->tableWidget->setItem(i,4*j+5,item);
                item=new QTableWidgetItem(paraStrVal);
                ui->tableWidget->setItem(i,4*j+6,item);
            }
        }
    }
}

void MainWindow::addWarpper()
{
    exec->addWarppedFunction("layout",layoutWrapper);
    exec->addWarppedFunction("createPoint",createPointWrapper);
    exec->addWarppedFunction("getCoordOfPoint",getCoordOfPointWrapper);
    exec->addWarppedFunction("deletePoint",deletePointWrapper);
    exec->addWarppedFunction("getSurfaceArea",getSurfaceArea);
    exec->addWarppedFunction("fun1",fun1_warpper);//int[]
    exec->addWarppedFunction("fun2", fun2_warpper);//int
    exec->addWarppedFunction("fun3", fun3_warpper);//constchar*
    exec->addWarppedFunction("fun4", fun4_warpper);//double
    exec->addWarppedFunction("fun5", fun5_warpper);//double[]
    exec->addWarppedFunction("fun6", fun6_warpper);//string
    exec->addWarppedFunction("fun7", fun7_warpper);//vector<string> in
    exec->addWarppedFunction("fun8", fun8_warpper);//vector<string> out
    exec->addWarppedFunction("fun9", fun9_warpper);//vector<double>
    exec->addWarppedFunction("fun10", fun10_warpper);//vector<int>
    exec->addWarppedFunction("fun11", fun11_warpper);//char
    exec->addWarppedFunction("fun12", fun12_warpper);//bool
}


void MainWindow::doOpenLogFile()
{
    ui->plainTextEdit->clear();
    ui->plainTextEdit_2->clear();
    //QDir::setCurrent("D:")
    QString path=QFileDialog::getOpenFileName(this,"open a log file","D:\\");
    if(path.isNull()){
        ui->actionExecute->setEnabled(false);
        return;
    }
    if(executerIsCreated()){
        delete exec;
        exec=new LogExecuter(path.toStdString());
    }else{
        exec=new LogExecuter(path.toStdString());
    }
    addWarpper();

    ui->lineEdit->setText(path);
    ui->lineEdit_2->setText(QString::fromStdString(exec->getOutputLogFilePath()));
    std::string originalFileText=exec->readLogFile(path.toStdString());
    ui->plainTextEdit->appendPlainText(QString::fromStdString(originalFileText));
    ui->plainTextEdit_2->appendPlainText(QString::fromStdString(originalFileText));
    initTableWidget();
    ui->actionExecute->setEnabled(true);
}




void MainWindow::on_actionOpen_triggered()
{
    doOpenLogFile();
}


void MainWindow::on_actionExecute_triggered()
{
    if(exec->getCurIndex()>=exec->getMaxIndex()||exec->getLogFilePath()==""){
        return;
    }
    auto map=exec->getFuncMap();
    std::string nextFuncName = exec->getCalls().at(exec->getCurIndex()+1).name;
    if(!exec->hasRegistered(nextFuncName)){

        QString text="["+QString::fromStdString(exec->getCurrentTime())+"]"+"error:"+QString::fromStdString(nextFuncName)+" is not registered!";
        QListWidgetItem* item = new QListWidgetItem(text);
        ui->listWidget->addItem(item);
        return;
    }

    if(ui->comboBox->currentIndex()==0){

        exec->executeNextCall();

        ui->plainTextEdit->clear();
        ui->plainTextEdit->appendPlainText(QString::fromStdString(exec->readLogFile(exec->getOutputLogFilePath())));
        ui->tableWidget->selectRow(exec->getCurIndex());
        int curIndex=exec->getCurIndex();
        QString time=QString::fromStdString(exec->getTimers().at(curIndex-1));
        QTableWidgetItem* itemTime=new QTableWidgetItem(time);
        ui->tableWidget->setItem(curIndex-1,2,itemTime);
        time=QString::fromStdString(exec->getTimers().at(curIndex));
        itemTime=new QTableWidgetItem(time);
        ui->tableWidget->setItem(curIndex,2,itemTime);
        std::vector<FunctionCall> calls=exec->getCalls();
        std::vector<std::string> timers=exec->getTimers();
        QString message="["+QString::fromStdString(timers[curIndex-1])+"]:"+QString::fromStdString(calls[curIndex-1].name)+" executed";
        QListWidgetItem* item=new QListWidgetItem(message);
        ui->listWidget->addItem(item);
        QString message2="["+QString::fromStdString(timers[curIndex])+"]:"+QString::fromStdString(calls[curIndex].name)+" finished";
        item=new QListWidgetItem(message2);
        ui->listWidget->addItem(item);

        std::vector<Parameter> paras=calls[curIndex].parameters;
        if(paras.size()){
            for(int i=0;i<paras.size();i++){
                QTableWidgetItem* item=new QTableWidgetItem(QString::fromStdString(paras[i].stringValue));
                ui->tableWidget->setItem(curIndex,4*i+6,item);
            }
        }
    }else{
        exec->executeAllCalls();
        ui->plainTextEdit->clear();
        ui->plainTextEdit->appendPlainText(QString::fromStdString(exec->readLogFile(exec->getOutputLogFilePath())));
        QTableWidgetItem* itemTime=nullptr;
        std::vector<std::string> timers=exec->getTimers();
        std::vector<FunctionCall> calls=exec->getCalls();

        for(int i=0;i<exec->getTimers().size();i++){
            QString time=QString::fromStdString(exec->getTimers().at(i));
            itemTime=new QTableWidgetItem(time);
            ui->tableWidget->setItem(i,2,itemTime);
            if(i%2==0){
                QString message="["+QString::fromStdString(timers[i])+"]:"+QString::fromStdString(calls[i].name)+" executed";
                QListWidgetItem* item=new QListWidgetItem(message);
                ui->listWidget->addItem(item);
            }else{
                QString message="["+QString::fromStdString(timers[i])+"]:"+QString::fromStdString(calls[i].name)+" executed";
                QListWidgetItem* item=new QListWidgetItem(message);
                ui->listWidget->addItem(item);
            }
        }

        for(int i=1;i<exec->getCalls().size();i+=2){
            std::vector<Parameter> paras=calls[i].parameters;
            if(paras.size()){
                for(int j=0;j<paras.size();j++){
                    QTableWidgetItem* item=new QTableWidgetItem(QString::fromStdString(paras[j].stringValue));
                    ui->tableWidget->setItem(i,3*j+6,item);
                }
            }
        }
    }
}

void MainWindow::on_actionResetCur_triggered()
{
    exec->setCurIndex(-1);
}


void MainWindow::on_actionSet_triggered()
{
    //exec->setCurIndex()
}


void MainWindow::on_actionExit_triggered()
{

    this->close();
}


void MainWindow::on_actionClear_triggered()
{
    ui->plainTextEdit->clear();
    ui->plainTextEdit_2->clear();
    delete exec;
    exec=nullptr;
    ui->comboBox->setCurrentIndex(0);
    ui->actionExecute->setEnabled(false);
    ui->tableWidget->clear();
    ui->listWidget->clear();
    ui->lineEdit->clear();
    ui->lineEdit_2->clear();
}

